package com.pig4cloud.pig.juhe.admin.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.pig4cloud.pig.common.core.util.DateUtil;
import com.pig4cloud.pig.juhe.admin.config.JuheProperties;
import com.pig4cloud.pig.juhe.admin.mapper.JuheGamePageMapper;
import com.pig4cloud.pig.juhe.admin.mapper.JuhePackMapper;
import com.pig4cloud.pig.juhe.admin.service.AsyncService;
import com.pig4cloud.pig.juhe.api.entity.JuheGamePage;
import com.pig4cloud.pig.juhe.api.entity.JuhePack;
import com.pig4cloud.pig.juhe.api.util.ApkIconUtil;
import com.pig4cloud.pig.juhe.api.util.ApkInfo;
import com.pig4cloud.pig.juhe.api.util.ApkUtil;
import com.pig4cloud.pig.juhe.api.util.AppUtils;
import com.pig4cloud.pig.juhe.api.util.ChineseCharacterUtil;
import com.pig4cloud.pig.juhe.api.util.Constant;
import com.pig4cloud.pig.juhe.api.util.PythonUtil;
import com.pig4cloud.pig.juhe.api.vo.AsyncPackInfoData;
import com.pig4cloud.pig.juhe.api.vo.ChannelConfig;
import com.pig4cloud.pig.juhe.api.vo.JuheChannelAttrValueVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.dom4j.DocumentException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

/**
 * @author yuwenfeng
 * @description: 异步服务
 * @date 2021/10/11 10:33
 */
@Service
@AllArgsConstructor
@Slf4j
public class AsyncServiceImpl implements AsyncService {

	private final JuheGamePageMapper juheGamePageMapper;

	private final JuhePackMapper juhePackMapper;

	private final JuheProperties juheProperties;

	@Async("juheExecutor")
	@Override
	public void fetchApkInfo(Long pageId) {
		JuheGamePage gamePage = juheGamePageMapper.selectOne(new QueryWrapper<JuheGamePage>().eq("page_id", pageId).eq("page_status", Constant.PAGE_STATUS_WAIT));
		if (null != gamePage) {
			String apkName = gamePage.getPageUrl().substring(gamePage.getPageUrl().lastIndexOf(StrUtil.SLASH) + 1);
			String apkPath = juheProperties.getJuheFileDir() + Constant.FILE_PACKAGE_IN + File.separator + apkName;
			try {
				ApkInfo apkInfo = new ApkUtil().getApkInfo(apkPath);
				log.info("apkInfo:{}", JSONObject.toJSONString(apkInfo));
				if (null != apkInfo && StringUtils.isNotBlank(apkInfo.getSuitableApplicationIcon())) {
					String extensionName = apkInfo.getSuitableApplicationIcon().substring(apkInfo.getSuitableApplicationIcon().lastIndexOf('.') + 1);
					if (Constant.PNG.equalsIgnoreCase(extensionName)) {
						String iconName = DateUtil.dateToString() + AppUtils.getAppId() + StrUtil.DOT + Constant.PNG;
						ApkIconUtil.extractFileFromApk(apkPath, apkInfo.getSuitableApplicationIcon(), juheProperties.getJuheFileDir() + Constant.FILE_IMAGES_PATH + File.separator + iconName);
						gamePage.setPageInfo(JSON.toJSONString(apkInfo));
						gamePage.setPagePackage(apkInfo.getPackageName());
						gamePage.setPageName(apkInfo.getApplicationLable());
						gamePage.setPageIcon(juheProperties.getJuheFilePath() + Constant.FILE_IMAGES_PATH + StrUtil.SLASH + iconName);
						gamePage.setPageVersion(apkInfo.getVersionCode());
						gamePage.setPageStatus(Constant.PAGE_STATUS_SUCC);
					} else {
						log.error("母包记录" + gamePage.getPageId() + "：{}", "图片无法识别");
						gamePage.setPageStatus(Constant.PAGE_STATUS_FAIL);
					}
				} else {
					log.error("母包记录" + gamePage.getPageId() + "：{}", "读包失败");
					gamePage.setPageStatus(Constant.PAGE_STATUS_FAIL);
				}
			} catch (Exception e) {
				log.error("母包记录" + gamePage.getPageId() + "：", e);
				gamePage.setPageStatus(Constant.PAGE_STATUS_FAIL);
			} finally {
				gamePage.setUpdateTime(new Date());
				juheGamePageMapper.updateById(gamePage);
			}
		}
	}

	@Async("juheExecutor")
	@Override
	public void packChannelApk(List<AsyncPackInfoData> packDataList) {
		log.info("----------------分包服务开始-------------------");
		if (CollectionUtils.isNotEmpty(packDataList)) {
			JSONArray jsonArrayParam = new JSONArray();
			List<ChannelConfig> configList;
			try {
				configList = PythonUtil.getPythonConfig(juheProperties.getChannelConfigPath());
			} catch (DocumentException e) {
				log.error("读取渠道文件配置失败：", e);
				batchUpdatePackFail(packDataList);
				return;
			}
			if (CollectionUtils.isNotEmpty(configList)) {
				String apkPath = "";
				for (AsyncPackInfoData packData : packDataList) {
					JSONObject jsonData = new JSONObject();
					for (ChannelConfig config : configList) {
						if (packData.getChannelInfo().getChannelName().equals(config.getName())) {
							jsonData.clear();
							jsonData = JSON.parseObject(JSON.toJSONString(config));
						}
					}
					if (jsonData.isEmpty()) {
						log.error("打包记录" + packData.getPackId() + "：{}", "渠道信息构造失败");
						updatePackFail(packData.getPackId());
						continue;
					}
					//解析包信息(默认图片地址)
					if (StringUtils.isNotBlank(packData.getGameChannel().getIconPath())) {
						String iconPathName = packData.getGameChannel().getIconPath().substring(packData.getGameChannel().getIconPath().lastIndexOf(StrUtil.SLASH) + 1);
//										jsonData.put("iconPath", Constant.WINDOWS_FILE_DIR + iconPathName);
						jsonData.put("iconPath", juheProperties.getJuheFileDir() + Constant.FILE_IMAGES_PATH + File.separator + iconPathName);
					} else {
						String iconPathName = packData.getGamePage().getPageIcon().substring(packData.getGamePage().getPageIcon().lastIndexOf(StrUtil.SLASH) + 1);
						jsonData.put("iconPath", juheProperties.getJuheFileDir() + Constant.FILE_IMAGES_PATH + File.separator + iconPathName);
					}
					for (JuheChannelAttrValueVo attrValue : packData.getAttrValueList()) {
						//华为文件处理
						if (Constant.OPEN_TYPE_HUAWEI.equals(packData.getChannelInfo().getChannelName()) && Constant.HUAWEI_JSON_KEY.equals(attrValue.getAttrKey())) {
							String jsonFileName = attrValue.getAttrValue().substring(attrValue.getAttrValue().lastIndexOf(StrUtil.SLASH) + 1);
//											String jsonFilePath = Constant.WINDOWS_FILE_DIR + jsonFileName;
							String jsonFilePath = juheProperties.getJuheFileDir() + Constant.FILE_IMAGES_PATH + File.separator + jsonFileName;
							JSONArray paramsListarray = new JSONArray();
							JSONObject itemJson = new JSONObject();
							itemJson.put("old_item1", "/assets/agconnect-services.json");
							itemJson.put("new_item1", jsonFilePath);
							paramsListarray.add(itemJson);
							jsonData.put("paramsList", paramsListarray);
						} else {
							jsonData.put(attrValue.getAttrKey(), attrValue.getAttrValue());
						}
					}
					String apkName = packData.getGamePage().getPageUrl().substring(packData.getGamePage().getPageUrl().lastIndexOf(StrUtil.SLASH) + 1);
					apkPath = juheProperties.getJuheFileDir() + Constant.FILE_PACKAGE_IN + File.separator + apkName;
					jsonData.put(Constant.PACKAGE_PACK_ID, packData.getPackId().toString());
					jsonData.put(Constant.PACKAGE_GAME_NAME, packData.getGameInfo().getGameName());
					jsonData.put(Constant.PACKAGE_CHANNEL_NAME, packData.getChannelInfo().getChannelName());
					jsonArrayParam.add(jsonData);
				}
				String packParam = jsonArrayParam.toString();
				log.info("分包参数packParam：{}", packParam);
				String base64 = new Base64().encodeToString(packParam.getBytes(StandardCharsets.UTF_8));
				log.info("分包参数base64:{}", base64);
				BufferedReader in = null;
				try {
					String[] strs = new String[]{juheProperties.getJuhePythonCmd(), juheProperties.getJuhePackagePythonPath(), apkPath, base64, ApkUtil.generateFileName()};
					Process process = Runtime.getRuntime().exec(strs);
					in = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
					String line, outPackagePath, packId, juheGameName, juheChannelName;
					JuhePack info;
					while ((line = in.readLine()) != null) {
						log.info("python返回值：{}", line);
						if (line.indexOf(Constant.PACKAGE_PACK_KEY) > 0) {
							outPackagePath = JSON.parseObject(line).getString(Constant.PACKAGE_PACK_KEY);
							packId = JSON.parseObject(line).getString(Constant.PACKAGE_PACK_ID);
							juheGameName = JSON.parseObject(line).getString(Constant.PACKAGE_GAME_NAME);
							juheChannelName = JSON.parseObject(line).getString(Constant.PACKAGE_CHANNEL_NAME);
							log.info("python转换值outPackagePath：{},packId:{}", outPackagePath, packId);
							String outPackageName = ChineseCharacterUtil.getSpells(juheGameName) + StrUtil.DASHED + juheChannelName + StrUtil.DASHED + DateUtil.dateToString() + StrUtil.DOT + Constant.APK;
							FileUtils.copyFile(new File(outPackagePath), new File(juheProperties.getJuheFileDir() + Constant.FILE_PACKAGE_OUT + File.separator + outPackageName));
							info = juhePackMapper.selectOne(new QueryWrapper<JuhePack>().eq("pack_id", Long.valueOf(packId)).eq("pack_status", Constant.PACKAGE_STATUS_WAIT));
							if (null != info) {
								info.setPackStatus(Constant.PACKAGE_STATUS_SUCC);
								info.setPackUrl(juheProperties.getJuheFilePath() + Constant.FILE_PACKAGE_OUT + StrUtil.SLASH + outPackageName);
								juhePackMapper.updateById(info);
							}
						}
					}
					in.close();
				} catch (Exception e) {
					log.error("Python分包错误：", e);
				} finally {
					if (null != in) {
						try {
							in.close();
						} catch (IOException e) {
							log.error("分包关闭读取流报错：", e);
						}
					}
					//未返回的视为分包失败
					batchUpdatePackFail(packDataList);
				}
			}
		}
		log.info("----------------分包服务结束-------------------");
	}

	private void batchUpdatePackFail(List<AsyncPackInfoData> packDataList) {
		if (CollectionUtils.isNotEmpty(packDataList)) {
			JuhePack info;
			for (AsyncPackInfoData packData : packDataList) {
				info = juhePackMapper.selectOne(new QueryWrapper<JuhePack>().eq("pack_id", packData.getPackId()).eq("pack_status", Constant.PACKAGE_STATUS_WAIT));
				if (null != info) {
					info.setPackStatus(Constant.PACKAGE_STATUS_FAIL);
					juhePackMapper.updateById(info);
				}
			}
		}
	}

	private void updatePackFail(Long packId) {
		JuhePack info = juhePackMapper.selectOne(new QueryWrapper<JuhePack>().eq("pack_id", packId).eq("pack_status", Constant.PACKAGE_STATUS_WAIT));
		if (null != info) {
			info.setPackStatus(Constant.PACKAGE_STATUS_FAIL);
			juhePackMapper.updateById(info);
		}
	}

}
